package com.stylefeng.guns.gateway.modular.order;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.rpc.RpcContext;
import com.baomidou.mybatisplus.plugins.Page;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import com.stylefeng.guns.api.alipay.AliPayServiceAPI;
import com.stylefeng.guns.api.alipay.vo.AliPayInfoVO;
import com.stylefeng.guns.api.alipay.vo.AliPayResultVO;
import com.stylefeng.guns.api.order.OrderServiceAPI;
import com.stylefeng.guns.api.order.vo.OrderVO;
import com.stylefeng.guns.core.base.controller.BaseController;
import com.stylefeng.guns.core.util.TokenBucket;
import com.stylefeng.guns.core.util.ToolUtil;
import com.stylefeng.guns.gateway.common.CurrentUser;
import com.stylefeng.guns.gateway.modular.vo.ResponseVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.Collection;

/**
 * @author dengwubo
 */
@RestController
@RequestMapping("/order/")
@Slf4j
public class OrderController extends BaseController {
    private static final String IMG_PRE = "http://img.meetingshop.cn/";

    @Reference(group = "order2018")
    private OrderServiceAPI orderServiceAPI;

    @Reference(group = "order2017")
    private OrderServiceAPI orderServiceAPI2017;

    @Reference
    private AliPayServiceAPI aliPayServiceAPI;


    TokenBucket tokenBucket = new TokenBucket();


    public ResponseVO error(String fieldId, String soldSeats, String seatsName) {

        return ResponseVO.serviceFail("抱歉,下单的人太多了,请稍后重试");

    }

    /**
     * 购票
     * <p>
     * Hystrix保护机制 : 信号量隔离 | 线程池隔离 | 线程切换
     *
     * @param fieldId
     * @param soldSeats
     * @param seatsName
     * @return
     */
    @HystrixCommand(
            fallbackMethod = "error",
            commandProperties = {
                    @HystrixProperty(name = "execution.isolation.strategy", value = "THREAD"),  // 隔离策略
                    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "4000"), // 超时时间
                    @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"), // 一个统计窗口内出现熔断的最小次数
                    @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "50") // 出错百分比阈值
            },
            threadPoolProperties = {
                    @HystrixProperty(name = "coreSize", value = "1"),
                    @HystrixProperty(name = "maxQueueSize", value = "10"),
                    @HystrixProperty(name = "keepAliveTimeMinutes", value = "1000"),
                    @HystrixProperty(name = "queueSizeRejectionThreshold", value = "8"),
                    @HystrixProperty(name = "metrics.rollingStats.numBuckets", value = "12"),
                    @HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds", value = "1500")
            })
    @RequestMapping("buyTickets")
    public ResponseVO buyTickets(String fieldId, String soldSeats, String seatsName) {


        try {
            if (tokenBucket.getToken()) {
                // 验证售出的票是否为真
                boolean isTrue = orderServiceAPI.isTrueSeats(fieldId, soldSeats);
                // 已经销售的座位里,有没有这些座位
                boolean isNotSold = orderServiceAPI.isNotSoldSeats(fieldId, soldSeats);
                // 创建订单信息,注意获取登陆人
                if (isTrue && isNotSold) {
                    String userId = CurrentUser.getCurrentUser();
                    if (StrUtil.isBlank(userId)) {
                        return ResponseVO.serviceFail("用户未登录");
                    }
                    OrderVO orderVO = orderServiceAPI.saveOrderInfo(Integer.parseInt(fieldId), soldSeats, seatsName, Integer.parseInt(userId));
                    if (orderVO == null) {
                        log.error("购票未成功");
                        return ResponseVO.serviceFail("购票未成功");
                    }
                    return ResponseVO.success(orderVO);
                } else {
                    return ResponseVO.serviceFail("订单中的座位编号有问题");
                }

            } else {
                return ResponseVO.serviceFail("购票人数过多,请稍后重试");
            }

        } catch (Exception e) {
            log.error("购票业务异常", e);
            return ResponseVO.serviceFail("购票业务异常");
        }


    }

    @RequestMapping("getOrderInfo")
    public ResponseVO getOrderInfo(@RequestParam(name = "nowPage", required = false, defaultValue = "1") Integer nowPage,
                                   @RequestParam(name = "pageSize", required = false, defaultValue = "5") Integer pageSize) {

        // 获取当前登陆人信息
        String userId = CurrentUser.getCurrentUser();
        // 使用当前登陆人获取已经购买的订单
        Page<OrderVO> page = new Page<>(nowPage, pageSize);
        if (StrUtil.isNotBlank(userId)) {
            // 根据FieldId 获取所有已经销售的座位编号
            Page<OrderVO> result = orderServiceAPI.getOrderByUserId(Integer.parseInt(userId), page);
            Page<OrderVO> result2017 = orderServiceAPI2017.getOrderByUserId(Integer.parseInt(userId), page);


            int totalPages = (int) (result.getPages() + result2017.getPages());

            Collection<OrderVO> orderVOList = CollectionUtil.union(result.getRecords(), result2017.getRecords());


            return ResponseVO.success(orderVOList, "", nowPage, totalPages);
        } else {
            return ResponseVO.serviceFail("用户未登录");
        }

    }

    /**
     * 获取支付二维码
     *
     * @param orderId
     * @return
     */
    @RequestMapping("getPayInfo")
    public ResponseVO getPayInfo(String orderId) {
        // 获取当前登陆人信息
        String userId = CurrentUser.getCurrentUser();
        if (StrUtil.isBlank(userId)) {
            return ResponseVO.serviceFail("用户未登录");

        }
        AliPayInfoVO qrCode = aliPayServiceAPI.getQRCode(orderId);


        return ResponseVO.success(qrCode, IMG_PRE);
    }

    /**
     * 获取支付结果
     *
     * @param orderId
     * @param tryNums
     * @return
     */
    @RequestMapping("getPayResult")
    public ResponseVO getPayResult(String orderId,
                                   @RequestParam(name = "tryNums", required = false, defaultValue = "1") Integer tryNums) {
        // 获取当前登陆人信息
        String userId = CurrentUser.getCurrentUser();
        if (StrUtil.isBlank(userId)) {
            return ResponseVO.serviceFail("用户未登录");

        }
        RpcContext.getContext().setAttachment("userId",userId);

        if (tryNums >= 4) {
            return ResponseVO.serviceFail("订单支付失败,请稍后重试");

        }

        AliPayResultVO aliPayResultVO = aliPayServiceAPI.getOrderStatus(orderId);

        if (ToolUtil.isEmpty(aliPayResultVO)) {
            AliPayResultVO serviceFailVO = new AliPayResultVO();
            serviceFailVO.setOrderId(orderId);
            serviceFailVO.setOrderStatus(0);
            serviceFailVO.setOrderMsg("支付失败");
            return ResponseVO.success(serviceFailVO);
        }


        return ResponseVO.success(aliPayResultVO);
    }


}
